﻿namespace NServiceBus.PersistenceTesting.Sagas;

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NUnit.Framework;

public class When_persisting_a_saga_with_record_type : SagaPersisterTests
{
    [Test]
    public async Task It_should_get_deep_copy()
    {
        var correlationPropertyData = Guid.NewGuid().ToString();
        var sagaData = new SagaWithRecordTypeEntity
        {
            Ints = [1, 2],
            CorrelationProperty = correlationPropertyData
        };

        await SaveSaga(sagaData);

        var retrieved = await GetById<SagaWithRecordTypeEntity>(sagaData.Id);

        Assert.That(retrieved.Ints, Is.EqualTo(sagaData.Ints).AsCollection);
        Assert.That(ReferenceEquals(sagaData.Ints, retrieved.Ints), Is.False);
    }

    [Test]
    public async Task It_Should_Load()
    {
        var correlationPropertyData = Guid.NewGuid().ToString();
        var person = new SagaWithNestedRecordTypeEntity.Person()
        {
            FirstName = "John",
            LastName = "Doe"
        };
        var sagaData =
            new SagaWithNestedRecordTypeEntity
            {
                SomePerson = person,
                CorrelationProperty = correlationPropertyData
            };

        await SaveSaga(sagaData);

        var retrieved = await GetById<SagaWithNestedRecordTypeEntity>(sagaData.Id);

        Assert.That(retrieved, Is.Not.Null);
        Assert.That(retrieved.SomePerson, Is.EqualTo(person));
    }

    public class SagaWithRecordType : Saga<SagaWithRecordTypeEntity>, IAmStartedByMessages<StartMessage>
    {
        public Task Handle(StartMessage message, IMessageHandlerContext context) => throw new NotImplementedException();

        protected override void ConfigureHowToFindSaga(SagaPropertyMapper<SagaWithRecordTypeEntity> mapper) => mapper.MapSaga(s => s.CorrelationProperty).ToMessage<StartMessage>(msg => msg.SomeId);
    }

    public class SagaWithNestedRecordType : Saga<SagaWithNestedRecordTypeEntity>,
        IAmStartedByMessages<StartMessage>
    {
        public Task Handle(StartMessage message, IMessageHandlerContext context) => throw new NotImplementedException();

        protected override void ConfigureHowToFindSaga(SagaPropertyMapper<SagaWithNestedRecordTypeEntity> mapper) => mapper.MapSaga(s => s.CorrelationProperty).ToMessage<StartMessage>(msg => msg.SomeId);
    }

    public class SagaWithNestedRecordTypeEntity : ContainSagaData
    {
        public string CorrelationProperty { get; set; }
        public Person SomePerson { get; set; }

        // A mutable record type. Immutable won't deserialize
        public record Person
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
        };
    }

    public record SagaWithRecordTypeEntity : IContainSagaData
    {
        public Guid Id { get; set; }
        public string Originator { get; set; }
        public string OriginalMessageId { get; set; }

        public string CorrelationProperty { get; set; }
        public List<int> Ints { get; set; }
    }

    public class StartMessage
    {
        public string SomeId { get; set; }
    }

    public When_persisting_a_saga_with_record_type(TestVariant param) : base(param)
    {
    }
}